﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../macro/head.h"
#include "objs.h"
#include "hook.h"
#include "mgr.h"

namespace xos_http
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    struct cmp_char
    {
        bool operator()(char const *a, char const *b) const
        {
            return mgr::crt()->strcmp( a, b ) < 0;
        }
    };

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    typedef std::map< const char *, const char *, cmp_char > HTTP_TYPE_MAP;
    typedef HTTP_TYPE_MAP::iterator HTTP_TYPE_ITER;

    static HTTP_TYPE_MAP * http_compress_type_map_ptr = 0;
    static HTTP_TYPE_MAP * http_content_type_map_ptr = 0;

    static xos_container::i_container * container_ptr = 0;
    static mgr * package_mgr_ptr = 0;

    static f_session session_fun_ptr = 0;
    static f_cookie cookie_fun_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    mgr::mgr()
    {
    }

    mgr::~mgr()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::static_init( xos_container::i_container * pContainer, i_http_mgr ** ppv )
    {
        int ret = 0;

        mgr::T * pObj = 0;

        if( ( 0 == ret ) && package_mgr_ptr )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            container_ptr = pContainer;
        }

        if( 0 == ret )
        {
            pObj = new mgr::T;
            if( !pObj )
            {
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            ret = pObj->init();
            if( 0 == ret )
            {
                package_mgr_ptr = pObj;
            }
            else
            {
                ret = 1;
            }
        }
        
        if( 0 != ret )
        {
            package_mgr_ptr = 0;
        }
        else
        {
            *ppv = pObj;
            pObj = 0;
        }

        xos_stl::release_interface( pObj );

        return ret;
    }

    xos_container::i_container * mgr::container()
    {
        return container_ptr;
    }

    xos_common::i_common * mgr::common()
    {
        return container()->common();
    }

    xos_common::i_misc * mgr::common_misc()
    {
        return container()->common_misc();
    }

    xos_box::i_serial * mgr::serial()
    {
        return container()->serial();
    }

    xos_common::i_md5 * mgr::md5()
    {
        xos_common::i_md5 * pRet = 0;
        common()->create( xos_common::OBJ_MD5, ( void** )&pRet );
        return pRet;
    }

    xos_log::i_log * mgr::log()
    {
        return container()->log();
    }

    xos::i_misc * mgr::misc()
    {
        return container()->misc();
    }

    xos::i_crt * mgr::crt()
    {
        return container()->crt();
    }

    xos_box::i_big_buf * mgr::big_buf()
    {
        return container_ptr->big_buf();
    }

    xos_box::i_buf * mgr::buf()
    {
        return container_ptr->buf();
    }

    xos::i_xos * mgr::xos()
    {
        return container()->xos();
    }

    mgr * mgr::get()
    {
        return package_mgr_ptr;
    }

    int mgr::valid_value( const char * lpszStr )
    {
        int ret = container()->common_misc()->valid( lpszStr, MAX_VALUE_LENGTH );
        ret = ( 0 == ret ) ? 0 : -1;
        return ret;
    }

    int mgr::valid_key( const char * lpszStr )
    {
        int ret = container()->common_misc()->valid( lpszStr, MAX_KEY_LENGTH );
        ret = ( 0 == ret ) ? 0 : -1;
        return ret;
    }

    int mgr::valid_uri( const char * lpszStr )
    {
        int ret = container()->common_misc()->valid( lpszStr, MAX_URI_LENGTH );
        ret = ( 0 == ret ) ? 0 : -1;
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::fmt_simple_html( char * lpszOut, int nSize, int * pnSize, const char * lpszTitle, const char * lpszInfo )
    {
        int ret = 0;

        int len = mgr::crt()->sprintf( lpszOut, nSize, 
"<!DOCTYPE html>\r\n\
<html>\r\n\
<head>\r\n\
<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\r\n\
<title>%s</title>\r\n\
</head>\r\n\r\n\
<body>\r\n\
<p>%s</p>\r\n\
</body>\r\n\
</html>", 
        lpszTitle, lpszInfo );

        if( pnSize )
        {
            *pnSize = len;
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::init_compress_type( xos_box::i_list * pTypeList )
    {
        int ret = 0;

        HTTP_TYPE_MAP & mp = *http_compress_type_map_ptr;
        xos_box::i_variant * pVT = 0;
        pTypeList->reset();

        while( ( pVT = ( xos_box::i_variant * )pTypeList->next() ) )
        {
            xos_box::i_property * pProp = pVT->prop( 0 );
            const char * lpszType = pProp->str( "type" );
            mp[lpszType] = lpszType;
        }

        return ret;
    }

    const char * mgr::compress_type( const char * lpszType )
    {
        int ret = 0;

        HTTP_TYPE_MAP & mp = *http_compress_type_map_ptr;
        const char * pRet = 0;

        if( 0 == ret )
        {
            HTTP_TYPE_ITER iter = mp.find( lpszType );
            if( iter != mp.end() )
            {
                pRet = iter->second;
            }
        }

        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::init_content_type( xos_box::i_list * pTypeList )
    {
        int ret = 0;

        HTTP_TYPE_MAP & mp = *http_content_type_map_ptr;
        xos_box::i_variant * pVT = 0;
        pTypeList->reset();

        while( ( pVT = ( xos_box::i_variant * )pTypeList->next() ) )
        {
            xos_box::i_property * pProp = pVT->prop( 0 );
            const char * lpszName = pProp->str( "extension" );
            const char * lpszType = pProp->str( "type" );
            mp[lpszName] = lpszType;
        }

        return ret;
    }

    const char * mgr::content_type( const char * lpszFile )
    {
        int ret = 0;

        HTTP_TYPE_MAP & mp = *http_content_type_map_ptr;
        const char * lpszExt = 0;
        const char * pRet = 0;

        if( 0 == ret )
        {
            lpszExt = mgr::common_misc()->ext( lpszFile, 0, 0, 0 );
            if( !lpszExt )
            {
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            HTTP_TYPE_ITER iter = mp.find( lpszExt );
            if( iter != mp.end() )
            {
                pRet = iter->second;
            }
        }

        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::get_gz_file_if_awailable( char * lpszDstFullFile, int nDstLen, const char * lpszSrcFullFile )
    {
        int ret = 0;

        xos::i_dir * pDir = 0;
        char name[4096];

        // 在相同位置找同名的.gz文件
        if( 0 == ret )
        {
            mgr::crt()->strcpy( name, sizeof( name ), lpszSrcFullFile );
            mgr::crt()->strcat( name, sizeof( name ), ".gz" );
            mgr::xos()->create( xos::i_xos::XOS_OBJ_DIR, ( void** )&pDir );
            ret = pDir->is_file_exist( name );
        }

        if( 0 == ret )
        {
            mgr::crt()->strcpy( lpszDstFullFile, nDstLen, name );
        }

        xos_stl::release_interface( pDir );

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    f_session mgr::session_callback( f_session * ppFun )
    {
        f_session pRet = session_fun_ptr;
        if( ppFun )
        {
            session_fun_ptr = *ppFun;
            pRet = *ppFun;
        }
        return pRet;
    }

    f_cookie mgr::cookie_callback( f_cookie * ppFun )
    {
        f_cookie pRet = cookie_fun_ptr;
        if( ppFun )
        {
            cookie_fun_ptr = *ppFun;
            pRet = *ppFun;
        }
        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // 创建package功能接口
    // 
    int mgr::create( enumObj obj, void ** ppv )
    {
        int ret = 0;

        switch( obj )
        {
        case OBJ_COMPOSE_REQUEST:
            {
                compose_request_impl * pRet = compose_request_impl::get_item_from_pool( true );
                pRet->init();
                *ppv = pRet;
            }
            break;
        case OBJ_PARSE_REQUEST:
            {
                parse_request_impl * pRet = parse_request_impl::get_item_from_pool( true );
                pRet->init();
                *ppv = pRet;
            }
            break;
        case OBJ_COMPOSE_RETURN:
            {
                compose_return_impl * pRet = compose_return_impl::get_item_from_pool( true );
                pRet->init();
                *ppv = pRet;
            }
            break;
        case OBJ_PARSE_RETURN:
            {
                parse_return_impl * pRet = parse_return_impl::get_item_from_pool( true );
                pRet->init();
                *ppv = pRet;
            }
            break;
        case OBJ_COOKIE:
            {
                cookie * pRet = cookie::get_item_from_pool( true );
                pRet->init();
                *ppv = pRet;
            }
            break;
        case OBJ_SESSION:
            {
                session * pRet = session::get( 0 );
                *ppv = pRet;
            }
            break;
        default:
            {
                ret = 1;
            }
            break;
        }

        return ret;
    }

    int mgr::heart( int interval_ms )
    {
        int ret = 0;
        session::heart( interval_ms );
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::put_back_to_pool( T * pT, bool bLock )
    {
        int ret = 0;
        delete this;
        return ret;
    }

    int mgr::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            log()->add_log_module( HTTP_LOG, 1 );
            log()->add_log_module( HTTP_LOG, 2 );
            log()->add_log_module( HTTP_LOG, 3 );
            log()->add_log_module( HTTP_LOG, 4 );
        }

        if( 0 == ret )
        {
            xos_stl::init_obj( http_compress_type_map_ptr );
        }

        if( 0 == ret )
        {
            xos_stl::init_obj( http_content_type_map_ptr );
        }

        if( 0 == ret )
        {
            ret = hook::init();
        }

        return ret;
    }

    int mgr::term()
    {
        int ret = 0;

        hook::term();

        xos_stl::term_obj( http_compress_type_map_ptr );
        xos_stl::term_obj( http_content_type_map_ptr );

        package_mgr_ptr = 0;
        container_ptr = 0;

        return ret;
    }

} // xos_http
